package top.huxy.boot.service.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import top.huxy.boot.config.RedisKeyConfig;
import top.huxy.boot.mapper.OperationLogMapper;
import top.huxy.boot.model.dto.Query;
import top.huxy.boot.model.entity.OperationLog;
import top.huxy.boot.service.OperationLogService;
import top.huxy.boot.util.ExceptionUtils;

import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @Classname OperationLogServiceImpl
 * @Description OperationLogServiceImpl
 * @Date 2021/9/25 11:45
 * @Created by huxy
 */
@Service
public class OperationLogServiceImpl implements OperationLogService {

    @Autowired
    RedisTemplate<String, Object> redisTemplate;

    @Autowired
    OperationLogMapper operationLogMapper;

    @Override
    public void saveOperationLog2Redis(OperationLog operationLog) {
        //保存到redis中
        redisTemplate.opsForList().rightPush(RedisKeyConfig.TEMP_OPERATION_LOG, operationLog);
    }

    @Override
    public List<OperationLog> getOperationLogList(Query query) {
        return operationLogMapper.getOperationLogList(query.getQueryMap());
    }

    /**
     * 请在调用此方法前，获取锁对象
     *
     * @return
     */
    @Override
    public String saveRedisOperationLog2DB() {
        //获取总数
        Long size = redisTemplate.opsForList().size(RedisKeyConfig.TEMP_OPERATION_LOG);
        if (size == null || size == 0) return "未保存任何数据，因为size=" + size;

        StringBuilder sb = new StringBuilder();
        int errCount = 0;
        long length = size;
        long time_start = System.currentTimeMillis();

        for (int i = 0; i < length; i++) {
            //每次从最左边弹出元素
            Object o = redisTemplate.opsForList().leftPop(RedisKeyConfig.TEMP_OPERATION_LOG);
            //类型校验
            if (o instanceof OperationLog) {
                OperationLog obj = (OperationLog) o;
                try {
                    //保存到数据库
                    operationLogMapper.saveOperationLog(obj);
                } catch (Exception e) {
                    //出错则记录异常
                    ExceptionUtils.logError(e);
                    errCount++;
                }
            } else {
                String msg = "不是预期的值o instanceof OperationLog is false";
                ExceptionUtils.logError(new RuntimeException(msg));
                sb.append(msg).append("\n");
                errCount++;
            }
            //锁续命
            redisTemplate.expire(RedisKeyConfig.LOCK_SAVE_OPERATION_LOG, 30L, TimeUnit.SECONDS);
        }
        long time_end = System.currentTimeMillis();
        sb.append("执行消耗")
                .append(time_end - time_start)
                .append("毫秒。")
                .append("错误次数")
                .append(errCount)
                .append("。执行总数")
                .append(size);
        return sb.toString();
    }
}
